"""
商务数据分析作业 - 数据科学增强版
使用高级数据科学方法进行员工数据分析和人口数据可视化
"""

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from scipy import stats
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import warnings
warnings.filterwarnings('ignore')

# 设置样式
plt.style.use('seaborn-v0_8-darkgrid')
sns.set_palette("husl")
plt.rcParams['font.sans-serif'] = ['DengXian Bold', 'Microsoft YaHei UI Bold', 'SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['figure.dpi'] = 100

class AdvancedDataProcessor:
    """高级数据处理器"""
    
    def __init__(self):
        self.scaler = StandardScaler()
        self.data_summary = {}
    
    def load_and_profile(self, filepath, dataset_name):
        """加载数据并生成数据画像"""
        print(f"\n{'🔍 ' + dataset_name + ' 数据画像分析'}")
        print("="*60)
        
        try:
            if 'data.xlsx' in filepath:
                data = pd.read_excel(filepath, header=1)  # 员工数据第二行作为列名
            else:
                data = pd.read_excel(filepath)  # 人口数据正常读取
            
            # 基础信息
            print(f"📊 数据维度: {data.shape}")
            print(f"📝 数据类型分布:")
            dtype_counts = data.dtypes.value_counts()
            for dtype, count in dtype_counts.items():
                print(f"   {dtype}: {count}列")
            
            # 缺失值分析
            missing_stats = data.isnull().sum()
            missing_pct = (missing_stats / len(data) * 100).round(2)
            missing_df = pd.DataFrame({
                '缺失数量': missing_stats,
                '缺失比例(%)': missing_pct
            }).query('缺失数量 > 0')
            
            if not missing_df.empty:
                print(f"\n❗ 缺失值统计:")
                print(missing_df)
            else:
                print("\n✅ 无缺失值")
            
            # 数据质量评估
            duplicate_count = data.duplicated().sum()
            print(f"🔄 重复记录: {duplicate_count}条")
            
            self.data_summary[dataset_name] = {
                'shape': data.shape,
                'missing_rate': missing_stats.sum() / data.size,
                'duplicate_rate': duplicate_count / len(data)
            }
            
            return data
            
        except Exception as e:
            print(f"❌ 数据加载失败: {e}")
            return None

class EmployeeAnalyzer:
    """员工数据高级分析器"""
    
    def __init__(self, data):
        self.data = data.copy()
        self.processed_data = None
        
    def advanced_data_cleaning(self):
        """高级数据清洗"""
        print("\n🧹 执行高级数据清洗...")
        
        # 1. 智能缺失值处理
        numeric_cols = self.data.select_dtypes(include=[np.number]).columns
        categorical_cols = self.data.select_dtypes(include=['object']).columns
        
        # 数值列用中位数填充
        for col in numeric_cols:
            if self.data[col].isnull().any():
                median_val = self.data[col].median()
                self.data[col].fillna(median_val, inplace=True)
                print(f"   📊 {col}: 用中位数{median_val}填充")
        
        # 分类列用众数或"无"填充
        for col in categorical_cols:
            if self.data[col].isnull().any():
                if col in ['性别', '学历', '在职状态']:
                    mode_val = self.data[col].mode()
                    if not mode_val.empty:
                        self.data[col].fillna(mode_val[0], inplace=True)
                        print(f"   🏷️ {col}: 用众数'{mode_val[0]}'填充")
                    else:
                        self.data[col].fillna("无", inplace=True)
                        print(f"   🏷️ {col}: 用'无'填充")
                else:
                    self.data[col].fillna("无", inplace=True)
                    print(f"   🏷️ {col}: 用'无'填充")
        
        # 2. 去重
        initial_count = len(self.data)
        self.data = self.data.drop_duplicates()
        removed_count = initial_count - len(self.data)
        print(f"   🗑️ 删除重复记录: {removed_count}条")
        
        self.processed_data = self.data.copy()
        return self
    
    def salary_analysis(self):
        """工资数据深度分析"""
        print("\n💰 工资数据深度分析")
        print("="*50)
        
        # 清理工资数据
        salary_cols = ['基本工资', '应发工资', '实发工资']
        for col in salary_cols:
            if col in self.data.columns:
                # 处理工资格式
                self.data[f'{col}_cleaned'] = pd.to_numeric(
                    self.data[col].astype(str).str.replace(',', '').str.replace(' ', ''),
                    errors='coerce'
                )
        
        # 统计分析
        salary_col = '应发工资_cleaned'
        if salary_col in self.data.columns:
            valid_salary = self.data[salary_col].dropna()
            
            if not valid_salary.empty:
                # 描述性统计
                stats_summary = valid_salary.describe()
                print("📈 工资描述性统计:")
                print(stats_summary.round(2))
                
                # 异常值检测(IQR方法)
                Q1 = valid_salary.quantile(0.25)
                Q3 = valid_salary.quantile(0.75)
                IQR = Q3 - Q1
                lower_bound = Q1 - 1.5 * IQR
                upper_bound = Q3 + 1.5 * IQR
                
                outliers = valid_salary[(valid_salary < lower_bound) | (valid_salary > upper_bound)]
                print(f"\n🚨 检测到工资异常值: {len(outliers)}个")
                if len(outliers) > 0:
                    print(f"   异常值范围: {outliers.min():.2f} - {outliers.max():.2f}")
                
                # 工资分布可视化
                self._plot_salary_distribution(valid_salary)
                
        return self
    
    def _plot_salary_distribution(self, salary_data):
        """绘制工资分布图"""
        fig, axes = plt.subplots(2, 2, figsize=(15, 10))
        fig.suptitle('员工工资分布分析', fontsize=16, fontweight='bold')
        
        # 直方图
        axes[0,0].hist(salary_data, bins=30, alpha=0.7, color='skyblue', edgecolor='black')
        axes[0,0].set_title('工资分布直方图')
        axes[0,0].set_xlabel('应发工资(元)')
        axes[0,0].set_ylabel('频次')
        
        # 箱线图
        axes[0,1].boxplot(salary_data, patch_artist=True, 
                         boxprops=dict(facecolor='lightgreen', alpha=0.7))
        axes[0,1].set_title('工资分布箱线图')
        axes[0,1].set_ylabel('应发工资(元)')
        
        # Q-Q图
        stats.probplot(salary_data, dist="norm", plot=axes[1,0])
        axes[1,0].set_title('Q-Q图(正态性检验)')
        
        # 核密度估计
        axes[1,1].hist(salary_data, bins=30, density=True, alpha=0.7, color='lightcoral')
        salary_data.plot.kde(ax=axes[1,1], color='red', linewidth=2)
        axes[1,1].set_title('工资密度分布')
        axes[1,1].set_xlabel('应发工资(元)')
        
        plt.tight_layout()
        plt.savefig('工资分布分析_v4.png', dpi=300, bbox_inches='tight')
        plt.show()
    
    def demographic_analysis(self):
        """员工人口统计学分析"""
        print("\n👥 员工人口统计学分析")
        print("="*50)
        
        # 年龄分析
        if '年龄' in self.data.columns:
            age_stats = self.data['年龄'].describe()
            print("📊 年龄统计:")
            print(age_stats.round(2))
            
            # 年龄分组
            self.data['年龄组'] = pd.cut(self.data['年龄'], 
                                      bins=[0, 30, 40, 50, 60, 100],
                                      labels=['30以下', '30-40', '40-50', '50-60', '60以上'])
            
            age_group_counts = self.data['年龄组'].value_counts()
            print(f"\n👶 年龄组分布:")
            print(age_group_counts)
        
        # 性别分析
        if '性别' in self.data.columns:
            gender_counts = self.data['性别'].value_counts()
            gender_pct = self.data['性别'].value_counts(normalize=True) * 100
            print(f"\n👨👩 性别分布:")
            for gender in gender_counts.index:
                print(f"   {gender}: {gender_counts[gender]}人 ({gender_pct[gender]:.1f}%)")
        
        # 学历分析
        if '学历' in self.data.columns:
            edu_counts = self.data['学历'].value_counts()
            print(f"\n🎓 学历分布:")
            print(edu_counts)
        
        # 在职状态分析
        if '在职状态' in self.data.columns:
            status_counts = self.data['在职状态'].value_counts()
            print(f"\n💼 在职状态分布:")
            print(status_counts)
        
        return self
    
    def advanced_groupby_analysis(self):
        """高级分组分析"""
        print("\n📊 多维度交叉分析")
        print("="*50)
        
        if '应发工资_cleaned' in self.data.columns:
            salary_col = '应发工资_cleaned'
            valid_data = self.data[self.data[salary_col].notna()].copy()
            
            # 多维度分组分析
            if len(valid_data) > 0:
                # 学历-性别交叉分析
                if '学历' in valid_data.columns and '性别' in valid_data.columns:
                    cross_analysis = valid_data.groupby(['学历', '性别'])[salary_col].agg([
                        'mean', 'median', 'count', 'std'
                    ]).round(2)
                    print("🎓👨👩 学历-性别交叉工资分析:")
                    print(cross_analysis)
                
                # 年龄组-学历分析
                if '年龄组' in valid_data.columns and '学历' in valid_data.columns:
                    age_edu_analysis = valid_data.groupby(['年龄组', '学历'])[salary_col].mean().round(2)
                    print(f"\n👶🎓 年龄组-学历工资分析:")
                    print(age_edu_analysis)
                
                # 创建热力图
                self._create_salary_heatmap(valid_data, salary_col)
        
        return self
    
    def _create_salary_heatmap(self, data, salary_col):
        """创建工资热力图"""
        if '学历' in data.columns and '性别' in data.columns:
            pivot_table = data.pivot_table(values=salary_col, 
                                         index='学历', 
                                         columns='性别', 
                                         aggfunc='mean')
            
            plt.figure(figsize=(10, 6))
            sns.heatmap(pivot_table, annot=True, fmt='.0f', cmap='YlOrRd', 
                       cbar_kws={'label': '平均工资(元)'})
            plt.title('学历-性别工资热力图', fontsize=14, fontweight='bold')
            plt.tight_layout()
            plt.savefig('工资热力图_v4.png', dpi=300, bbox_inches='tight')
            plt.show()
    
    def employee_clustering(self):
        """员工聚类分析"""
        print("\n🎯 员工聚类分析")
        print("="*50)
        
        # 准备聚类数据
        cluster_features = []
        feature_names = []
        
        if '年龄' in self.data.columns:
            cluster_features.append(self.data['年龄'].fillna(self.data['年龄'].median()))
            feature_names.append('年龄')
        
        if '应发工资_cleaned' in self.data.columns:
            salary_data = self.data['应发工资_cleaned'].fillna(self.data['应发工资_cleaned'].median())
            cluster_features.append(salary_data)
            feature_names.append('工资')
        
        if len(cluster_features) >= 2:
            X = np.column_stack(cluster_features)
            
            # 数据标准化
            scaler = StandardScaler()
            X_scaled = scaler.fit_transform(X)
            
            # K-means聚类
            kmeans = KMeans(n_clusters=3, random_state=42)
            clusters = kmeans.fit_predict(X_scaled)
            
            self.data['聚类标签'] = clusters
            
            # 聚类结果分析
            cluster_summary = self.data.groupby('聚类标签').agg({
                '年龄': ['mean', 'count'],
                '应发工资_cleaned': 'mean'
            }).round(2)
            
            print("🏷️ 聚类结果汇总:")
            print(cluster_summary)
            
            # 聚类可视化
            self._plot_clusters(X, clusters, feature_names)
        
        return self
    
    def _plot_clusters(self, X, clusters, feature_names):
        """聚类结果可视化"""
        plt.figure(figsize=(10, 8))
        scatter = plt.scatter(X[:, 0], X[:, 1], c=clusters, cmap='viridis', alpha=0.7)
        plt.xlabel(feature_names[0])
        plt.ylabel(feature_names[1])
        plt.title('员工聚类分析结果', fontsize=14, fontweight='bold')
        plt.colorbar(scatter, label='聚类标签')
        plt.grid(True, alpha=0.3)
        plt.tight_layout()
        plt.savefig('员工聚类分析_v4.png', dpi=300, bbox_inches='tight')
        plt.show()
    
    def export_enhanced_data(self):
        """导出增强后的数据"""
        output_file = 'dataoutput.xlsx'
        self.data.to_excel(output_file, index=False)
        print(f"\n💾 增强数据已导出至: {output_file}")
        return self

class PopulationVisualizer:
    """人口数据高级可视化器"""
    
    def __init__(self, data):
        self.data = data.copy()
        self.prepare_data()
    
    def prepare_data(self):
        """数据预处理"""
        # 添加年份数值列
        self.data['年份_数值'] = self.data['年份'].str.replace('年', '').astype(int)
        
        # 计算衍生指标
        self.data['城镇化率'] = (self.data['城镇人口'] / self.data['年末总人口'] * 100).round(2)
        self.data['性别比'] = (self.data['男性人口'] / self.data['女性人口'] * 100).round(2)
        self.data['城乡比'] = (self.data['城镇人口'] / self.data['乡村人口']).round(2)
        
        print("📊 人口数据预处理完成")
        print(f"   城镇化率范围: {self.data['城镇化率'].min():.1f}% - {self.data['城镇化率'].max():.1f}%")
        print(f"   性别比范围: {self.data['性别比'].min():.1f} - {self.data['性别比'].max():.1f}")
    
    def advanced_statistical_analysis(self):
        """高级统计分析"""
        print("\n📈 人口数据高级统计分析")
        print("="*50)
        
        # 趋势分析
        years = self.data['年份_数值'].values
        urban_pop = self.data['城镇人口'].values
        rural_pop = self.data['乡村人口'].values
        
        # 计算增长率
        urban_growth = np.diff(urban_pop) / urban_pop[:-1] * 100
        rural_growth = np.diff(rural_pop) / rural_pop[:-1] * 100
        
        print("📊 年平均增长率:")
        print(f"   城镇人口: {urban_growth.mean():.2f}%")
        print(f"   乡村人口: {rural_growth.mean():.2f}%")
        
        # 相关性分析
        corr_matrix = self.data[['年末总人口', '男性人口', '女性人口', '城镇人口', '乡村人口']].corr()
        print(f"\n🔗 相关性矩阵:")
        print(corr_matrix.round(3))
        
        return self
    
    def create_comprehensive_visualization(self):
        """创建综合可视化报告"""
        print("\n🎨 生成综合可视化报告...")
        
        # 设置整体样式
        plt.style.use('seaborn-v0_8-whitegrid')
        fig = plt.figure(figsize=(20, 15))
        
        # 创建网格布局
        gs = fig.add_gridspec(3, 3, hspace=0.3, wspace=0.3)
        
        # 1. 城乡人口对比
        ax1 = fig.add_subplot(gs[0, :2])
        x = np.arange(len(self.data))
        width = 0.35
        ax1.bar(x - width/2, self.data['城镇人口'], width, label='城镇人口', color='#1f77b4', alpha=0.8)
        ax1.bar(x + width/2, self.data['乡村人口'], width, label='乡村人口', color='#ff7f0e', alpha=0.8)
        ax1.set_xlabel('年份')
        ax1.set_ylabel('人口数量（万人）')
        ax1.set_title('城乡人口对比趋势', fontsize=14, fontweight='bold')
        ax1.set_xticks(x)
        ax1.set_xticklabels(self.data['年份'].str.replace('年', ''), rotation=45)
        ax1.legend()
        ax1.grid(True, alpha=0.3)
        
        # 2. 性别比例饼图
        ax2 = fig.add_subplot(gs[0, 2])
        data_2022 = self.data[self.data['年份'] == '2022年']
        if not data_2022.empty:
            sizes = [data_2022['男性人口'].iloc[0], data_2022['女性人口'].iloc[0]]
            colors = ['#87CEEB', '#FFB6C1']
            ax2.pie(sizes, labels=['男性', '女性'], colors=colors, autopct='%1.1f%%', startangle=90)
            ax2.set_title('2022年性别比例')
        
        # 3. 城镇化率趋势
        ax3 = fig.add_subplot(gs[1, :])
        ax3.plot(self.data['年份_数值'], self.data['城镇化率'], 
                marker='o', linewidth=3, markersize=8, color='green')
        ax3.fill_between(self.data['年份_数值'], self.data['城镇化率'], alpha=0.3, color='green')
        ax3.set_xlabel('年份')
        ax3.set_ylabel('城镇化率 (%)')
        ax3.set_title('城镇化率发展趋势', fontsize=14, fontweight='bold')
        ax3.grid(True, alpha=0.3)
        
        # 4. 相关性热力图
        ax4 = fig.add_subplot(gs[2, :2])
        corr_data = self.data[['年末总人口', '男性人口', '女性人口', '城镇人口', '乡村人口']].corr()
        sns.heatmap(corr_data, annot=True, cmap='coolwarm', center=0, 
                   square=True, ax=ax4, cbar_kws={"shrink": .8})
        ax4.set_title('人口指标相关性分析', fontsize=14, fontweight='bold')
        
        # 5. 散点图矩阵
        ax5 = fig.add_subplot(gs[2, 2])
        ax5.scatter(self.data['年末总人口'], self.data['城镇人口'], 
                   c=self.data['年份_数值'], cmap='viridis', s=100, alpha=0.7)
        ax5.set_xlabel('年末总人口（万人）')
        ax5.set_ylabel('城镇人口（万人）')
        ax5.set_title('总人口与城镇人口关系')
        ax5.grid(True, alpha=0.3)
        
        plt.suptitle('中国人口发展分析综合报告 (2014-2022)', fontsize=20, fontweight='bold', y=0.98)
        plt.savefig('人口分析综合报告_v4.png', dpi=300, bbox_inches='tight')
        plt.show()

def main():
    """主程序"""
    print("🚀 启动商务数据分析高级版")
    print("="*80)
    
    # 初始化高级数据处理器
    processor = AdvancedDataProcessor()
    
    # ====================================
    # 任务一：员工数据高级分析
    # ====================================
    print("\n" + "="*30 + " 任务一：员工数据高级分析 " + "="*30)
    
    # 加载员工数据
    employee_data = processor.load_and_profile('data.xlsx', '员工')
    
    if employee_data is not None:
        # 创建员工分析器
        analyzer = EmployeeAnalyzer(employee_data)
        
        # 执行分析链
        analyzer.advanced_data_cleaning() \
                .salary_analysis() \
                .demographic_analysis() \
                .advanced_groupby_analysis() \
                .employee_clustering() \
                .export_enhanced_data()
        
        # 执行要求的基本操作
        print("\n📋 执行作业要求的基本操作:")
        
        # 显示前10行和后15行
        print("\n前10行数据:")
        print(analyzer.data.head(10))
        print("\n后15行数据:")
        print(analyzer.data.tail(15))
        
        # 在职员工统计
        active_count = len(analyzer.data[analyzer.data['在职状态'] == '在职'])
        print(f"\n在职员工人数: {active_count}")
        
        # 添加新员工GH993
        new_employee = pd.DataFrame([{
            '序号': 993, '工号': 'GH993', '姓名': '赵六', '性别': '女',
            '手机号': '13666666666', '年龄': 28, '在职状态': '在职',
            '学历': '本科', '应发工资': 8500
        }])
        analyzer.data = pd.concat([analyzer.data, new_employee], ignore_index=True)
        print("✅ 已添加员工GH993")
        
        # 更新990号员工手机号
        mask = analyzer.data['序号'] == 990
        if mask.any():
            analyzer.data.loc[mask, '手机号'] = '15012345678'
            print("✅ 已更新990号员工手机号")
        
        # 删除符合条件的员工
        condition = (analyzer.data['年龄'] > 55) & (analyzer.data['在职状态'] == '离职') & (analyzer.data['性别'] == '男')
        removed_count = condition.sum()
        analyzer.data = analyzer.data[~condition]
        print(f"✅ 已删除{removed_count}名符合条件的员工")
    
    # ====================================
    # 任务二：人口数据高级可视化
    # ====================================
    print("\n" + "="*30 + " 任务二：人口数据高级可视化 " + "="*30)
    
    # 加载人口数据
    population_data = processor.load_and_profile('population.xlsx', '人口')
    
    if population_data is not None:
        # 创建可视化器
        visualizer = PopulationVisualizer(population_data)
        
        # 执行高级可视化
        visualizer.advanced_statistical_analysis()
        visualizer.create_comprehensive_visualization()
    
    print("\n🎉 高级数据分析任务全部完成！")
    print("\n📁 生成的文件列表:")
    print("   📊 dataoutput.xlsx - 增强后的员工数据")
    print("   📈 工资分布分析_v4.png - 工资分布统计图")
    print("   🔥 工资热力图_v4.png - 学历性别工资热力图")
    print("   🎯 员工聚类分析_v4.png - 员工聚类结果")
    print("   📋 人口分析综合报告_v4.png - 综合分析报告")

if __name__ == "__main__":
    main() 